
package com.hlkj.pay.app.merchant.ext.impl.yeepay.ext;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderQueryContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelRefundPayOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.dto.YeePayAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.dto.YeePayConfig;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.handler.YeePayCommonParamsHandle;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.order.RefundOrderDO;
import com.hlkj.pay.util.DateUtils;
import com.yeepay.yop.sdk.auth.credentials.PKICredentialsItem;
import com.yeepay.yop.sdk.auth.credentials.YopPKICredentials;
import com.yeepay.yop.sdk.security.CertTypeEnum;
import com.yeepay.yop.sdk.service.aggpay.AggpayClient;
import com.yeepay.yop.sdk.service.aggpay.AggpayClientBuilder;
import com.yeepay.yop.sdk.service.aggpay.model.CloseOrderResponseDTO;
import com.yeepay.yop.sdk.service.aggpay.request.CloseOrderRequest;
import com.yeepay.yop.sdk.service.aggpay.response.CloseOrderResponse;
import com.yeepay.yop.sdk.service.trade.TradeClient;
import com.yeepay.yop.sdk.service.trade.TradeClientBuilder;
import com.yeepay.yop.sdk.service.trade.model.QueryRefundResponseDTO;
import com.yeepay.yop.sdk.service.trade.model.ResponseRefundDTO;
import com.yeepay.yop.sdk.service.trade.model.YopQueryOrderResDTO;
import com.yeepay.yop.sdk.service.trade.request.OrderQueryRequest;
import com.yeepay.yop.sdk.service.trade.request.RefundQueryRequest;
import com.yeepay.yop.sdk.service.trade.request.RefundRequest;
import com.yeepay.yop.sdk.service.trade.response.OrderQueryResponse;
import com.yeepay.yop.sdk.service.trade.response.RefundQueryResponse;
import com.yeepay.yop.sdk.service.trade.response.RefundResponse;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 易宝支付 正扫 反扫 通用处理
 * 
 * @author HlpayTeam
 * @date 2024/10/11 16:22
 */
@Slf4j
@Repository
@RequiredArgsConstructor
public class YeePaySceneCommonPayOrder {

    @Value("${hlkj.domain}")
    public String domain;

    @Autowired
    private  YeePayCommonParamsHandle yeePayCommonParamsHandle;

    private static final TradeClient tradeClient = TradeClientBuilder.builder().build();

    private static final AggpayClient aggpayClient = AggpayClientBuilder.builder().build();
    /**
     * 易宝支付查询支付订单
     * 
     * @param channelPayOrderContext
     */
    public void commonQueryChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderContext) {

        CommonResult<YeePayConfig> yeePayConfigCommonResult = yeePayCommonParamsHandle.yeePayConfig(channelPayOrderContext.getProviderChannelConfigDO(),
                channelPayOrderContext.isTest());
        if (!yeePayConfigCommonResult.isSuccess()) {
            channelPayOrderContext.setRemark(yeePayConfigCommonResult.getMsg());
            channelPayOrderContext.setProcessStatus(false);
            return;
        }
        // 支付订单信息
        PayOrderDO payOrderDO = channelPayOrderContext.getPayOrderDO();
        // 商户通道
        MerchantAppChannelDO merchantAppChannelDO = channelPayOrderContext.getMerchantAppChannelDO();
        // 易宝配置信息
        YeePayConfig yeePayConfig = yeePayConfigCommonResult.getData();
        try {
            YeePayAppChannelParams yeeAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YeePayAppChannelParams.class);

            OrderQueryRequest request = new OrderQueryRequest();
            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(yeePayCommonParamsHandle.getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));

            request.setMerchantNo(yeeAppChannelParams.getSubMchId());
            request.setOrderId(payOrderDO.getPayOrderNo());

            log.info("易宝订单查询 请求params参数:{}", JSONUtil.toJsonStr(request));
            OrderQueryResponse response = tradeClient.orderQuery(request);
            YopQueryOrderResDTO result = response.getResult();
            log.info("易宝订单查询 响应参数:{}", result);

            if ("OPR00000".equals(result.getCode())) {
                PayOrderDO updartePayOrderDO = new PayOrderDO();
                switch (result.getStatus()) {
                    case "PROCESSING":
                        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.PAYING.getCode());
                        updartePayOrderDO.setBankMsg("");
                        break;
                    case "SUCCESS":
                        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.SUCCESS.getCode());
                        updartePayOrderDO.setBankMsg("");
                        break;
                    case "TIME_OUT":
                    case "FAIL":
                        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.FAIL.getCode());
                        break;
                    case "CLOSE":
                        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.CLOSE.getCode());
                        break;
                }

                if (StringUtils.hasText(result.getPaySuccessDate())) {
                    try {
                        updartePayOrderDO.setSuccessTime(DateUtils.shanghaiDate(result.getPaySuccessDate(), DatePattern.NORM_DATETIME_PATTERN));
                    }
                    catch (Exception e) {
                        log.error("易宝订单查询返回 时间格式化错误 dateTime:{},message:{}", result.getPaySuccessDate(), e.getMessage());
                    }
                }
                updartePayOrderDO.setChannelOrderNo(result.getBankOrderId());
                updartePayOrderDO.setChannelOrderId(result.getUniqueOrderNo());
                updartePayOrderDO.setInsOrderNo(result.getChannelTrxId());
                if (result.getPayAmount() != null) {
                    updartePayOrderDO.setSettlementAmount(result.getPayAmount());
                    updartePayOrderDO.setPayAmount(result.getPayAmount());
                }

                if (result.getPayerInfo() != null) {
                    updartePayOrderDO.setUserId(result.getPayerInfo().getUserID());
                }
                channelPayOrderContext.setUpdartePayOrderDO(updartePayOrderDO);

            }else{
                String respDesc = result.getFailReason();
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(respDesc)) {
                    channelPayOrderContext.setRemark(respDesc);
                }
                else {
                    channelPayOrderContext.setRemark("易宝提交支付订单查询返回错误信息为空,错误码为:" + result.getMessage());
                }
            }

        }catch (Exception e){
            e.printStackTrace();
            log.error("易宝查询支付订单请求失败 message:{}", e.getMessage(), e);
            channelPayOrderContext.setRemark("易宝查询支付订单请求失败,失败信息" + e.getMessage());
            channelPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    /**
     * 易宝支付关闭订单
     * 
     * @param channelClosePayOrderContext
     */
    public void commonCloseChannelPayOrder(ChannelPayOrderQueryContext channelClosePayOrderContext) {

        CommonResult<YeePayConfig> yeePayConfigCommonResult = yeePayCommonParamsHandle.yeePayConfig(channelClosePayOrderContext.getProviderChannelConfigDO(),
                channelClosePayOrderContext.isTest());
        if (!yeePayConfigCommonResult.isSuccess()) {
            channelClosePayOrderContext.setRemark(yeePayConfigCommonResult.getMsg());
            channelClosePayOrderContext.setProcessStatus(false);
            return;
        }
        // 支付订单信息
        PayOrderDO payOrderDO = channelClosePayOrderContext.getPayOrderDO();
        // 商户通道
        MerchantAppChannelDO merchantAppChannelDO = channelClosePayOrderContext.getMerchantAppChannelDO();
        // 易宝配置信息
        YeePayConfig yeePayConfig = yeePayConfigCommonResult.getData();
        try {

            YeePayAppChannelParams yeeAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YeePayAppChannelParams.class);

            CloseOrderRequest request = new CloseOrderRequest();
            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(yeePayCommonParamsHandle.getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));

            request.setOrderId(payOrderDO.getPayOrderNo());
            request.setMerchantNo(yeeAppChannelParams.getSubMchId());

            log.info("易宝关闭支付订单 请求params参数:{}", JSONUtil.toJsonStr(request));
            CloseOrderResponse response = aggpayClient.closeOrder(request);
            CloseOrderResponseDTO result = response.getResult();
            log.info("易宝关闭支付订单 响应参数:{}", response);

            if ("00000".equals(result.getCode())) {
                PayOrderDO updartePayOrderDO = new PayOrderDO();
                updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.CLOSE.getCode());
                channelClosePayOrderContext.setUpdartePayOrderDO(updartePayOrderDO);
            }else{
                channelClosePayOrderContext.setProcessStatus(Boolean.FALSE);
                channelClosePayOrderContext.setRemark(result.getMessage());
            }

        }catch (Exception e){
            e.printStackTrace();
            log.error("易宝关闭支付订单请求失败 message:{}", e.getMessage(), e);
            channelClosePayOrderContext.setRemark("易宝查询支付订单请求失败,失败信息" + e.getMessage());
            channelClosePayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    /**
     * 易宝支付查询关闭订单状态
     * 
     * @param channelPayOrderQueryContext
     */
    public void commonQueryChannelClosePayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        PayOrderDO updartePayOrderDO = new PayOrderDO();
        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.CLOSE.getCode());
        channelPayOrderQueryContext.setUpdartePayOrderDO(updartePayOrderDO);
    }

    /**
     * 易宝支付订单退款
     * 
     * @param channelRefundPayOrderContext
     */
    public void commonRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {

        CommonResult<YeePayConfig> yeePayConfigCommonResult = yeePayCommonParamsHandle.yeePayConfig(channelRefundPayOrderContext.getProviderChannelConfigDO(),
                channelRefundPayOrderContext.isTest());
        if (!yeePayConfigCommonResult.isSuccess()) {
            channelRefundPayOrderContext.setRemark(yeePayConfigCommonResult.getMsg());
            channelRefundPayOrderContext.setProcessStatus(false);
            return;
        }
        // 支付订单信息
        PayOrderDO payOrderDO = channelRefundPayOrderContext.getPayOrderDO();
        // 退款信息
        RefundOrderDO refundOrderDO = channelRefundPayOrderContext.getRefundOrderDO();
        // 商户通道
        MerchantAppChannelDO merchantAppChannelDO = channelRefundPayOrderContext.getMerchantAppChannelDO();
        // 易宝配置信息
        YeePayConfig yeePayConfig = yeePayConfigCommonResult.getData();
        try {
            YeePayAppChannelParams yeeAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YeePayAppChannelParams.class);

            RefundRequest request = new RefundRequest();
            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(yeePayCommonParamsHandle.getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));

            request.setMerchantNo(yeeAppChannelParams.getSubMchId());
            request.setOrderId(payOrderDO.getPayOrderNo());
            request.setRefundRequestId(refundOrderDO.getRefundOrderNo());
            request.setRefundAmount(refundOrderDO.getRefundAmount().toString());
            request.setDescription(refundOrderDO.getRefundReason());

            log.info("易宝支付退款 请求params参数:{}", JSONUtil.toJsonStr(request));
            RefundResponse response = tradeClient.refund(request);
            ResponseRefundDTO result = response.getResult();
            log.info("易宝支付退款 响应参数:{}", result);

            if ("OPR00000".equals(result.getCode())) {
                RefundOrderDO updateRefundOrderDO = new RefundOrderDO();
                switch (result.getStatus()){
                    case "SUCCESS":
                        updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUND.getCode());
                        updateRefundOrderDO.setActualRefundAmount(NumberUtil.toBigDecimal(result.getRefundAmount()));
                        updateRefundOrderDO.setSuccessTime(DateUtils.shanghaiDate(result.getRefundRequestDate(), DatePattern.NORM_DATETIME_PATTERN));
                        break;
                    case "PROCESSING":
                        updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUNDING.getCode());
                        break;
                    case "CLOSED":
                    case "SUSPEND":
                        updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.FAIL.getCode());
                        break;
                }
                channelRefundPayOrderContext.setUpdateRefundOrderDO(updateRefundOrderDO);
            }else{
                channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelRefundPayOrderContext.setRemark(result.getMessage());
            }

        }catch (Exception e){
            e.printStackTrace();
            log.error("易宝支付退款请求失败 message:{}", e.getMessage(), e);
            channelRefundPayOrderContext.setRemark("易宝支付退款请求失败,失败信息" + e.getMessage());
            channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    /**
     * 易宝支付订单退款状态查询
     * 
     * @param channelRefundPayOrderContext
     */
    public void commonQueryRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {

        CommonResult<YeePayConfig> yeePayConfigCommonResult = yeePayCommonParamsHandle.yeePayConfig(channelRefundPayOrderContext.getProviderChannelConfigDO(),
                channelRefundPayOrderContext.isTest());
        if (!yeePayConfigCommonResult.isSuccess()) {
            channelRefundPayOrderContext.setRemark(yeePayConfigCommonResult.getMsg());
            channelRefundPayOrderContext.setProcessStatus(false);
            return;
        }
        // 支付订单信息
        PayOrderDO payOrderDO = channelRefundPayOrderContext.getPayOrderDO();
        // 退款信息
        RefundOrderDO refundOrderDO = channelRefundPayOrderContext.getRefundOrderDO();
        // 商户通道
        MerchantAppChannelDO merchantAppChannelDO = channelRefundPayOrderContext.getMerchantAppChannelDO();
        // 易宝配置信息
        YeePayConfig yeePayConfig = yeePayConfigCommonResult.getData();
        try {
            YeePayAppChannelParams yeeAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), YeePayAppChannelParams.class);

            RefundQueryRequest request = new RefundQueryRequest();
            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(yeePayCommonParamsHandle.getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));

            request.setMerchantNo(yeeAppChannelParams.getSubMchId());
            request.setOrderId(payOrderDO.getPayOrderNo());
            request.setRefundRequestId(refundOrderDO.getRefundOrderNo());

            log.info("易宝订单查询退款 请求params参数:{}", JSONUtil.toJsonStr(request));
            RefundQueryResponse response = tradeClient.refundQuery(request);
            QueryRefundResponseDTO result = response.getResult();
            log.info("易宝支付查询退款 响应参数:{}", result);

            RefundOrderDO updateRefundOrderDO = new RefundOrderDO();
            if ("OPR00000".equals(result.getCode())) {
                switch (result.getStatus()){
                    case "SUCCESS":
                        updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUND.getCode());
                        updateRefundOrderDO.setSuccessTime(DateUtils.shanghaiDate(result.getRefundRequestDate(), DatePattern.NORM_DATETIME_PATTERN));
                        break;
                    case "PROCESSING":
                        updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUNDING.getCode());
                        break;
                    case "CLOSED":
                    case "SUSPEND":
                        updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.FAIL.getCode());
                        break;
                }
            }else{
                channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelRefundPayOrderContext.setRemark(result.getMessage());
            }
            channelRefundPayOrderContext.setUpdateRefundOrderDO(updateRefundOrderDO);

        }catch (Exception e){
            e.printStackTrace();
            log.error("易宝支付查询退款请求失败 message:{}", e.getMessage(), e);
            channelRefundPayOrderContext.setRemark("易宝支付查询退款请求失败,失败信息" + e.getMessage());
            channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }


    public Integer expireMinute(Long time) {
        if (time == null) {
            return 30;
        }
        return (int) (time - System.currentTimeMillis()) / 1000 / 60;
    }


    public String reqTime() {
        return DateUtils.getDateString("yyyyMMddHHmmss");
    }

    public String openapiDomain(boolean test) {
        // 测试环境：https://test.wsmsd.cn/sit/api/v2/mms/openApi/wechatParamConf
        // 生产环境：https://s2.lakala.com/api/v2/mms/openApi/wechatParamConf
        if (test) {
            return "https://test.wsmsd.cn/sit";
        }
        else {
            return "https://s2.lakala.com";
        }
    }
}
